#define CHK_MEM_LEAK
#if defined(CHK_MEM_LEAK)
#   if defined(WIN32)
#      include "stdafx.h"
#      include <windows.h>
#      define _CRTDBG_MAP_ALLOC
#      include <crtdbg.h>
#   elif defined(linux)
#      include <stdio.h>
#   endif
#endif

#include "stdafx.h"
#include <locale.h>
#include "cppflibinc.h"


using namespace cppflib;
using namespace cppflib::collections;

void TestAllocation(void);
void TestCFString();
void TestCollections();
void TestThread(bool isFullTest);
void TestExceptions();
void TestLang();
void TestCustomClass();
void TestDataConversion(void);
void TestIO(void);
void TestUtil(void);
void TestNet(void);
void TestNetSSL(void);
void TestSqlite(void);
void TestXml(void);
void TestHttp(void);
void ConfigXmlFileList(bool isFullTest);
void TestJSON(void);
void TestCrypto(void);

static bool isPerformFullTest(ListCppObjT<CFString> * argList)
{
   for (int i = 0; i < static_cast<int>(argList->GetCount()); ++i) {
      if (*argList->Get(i) == _S("--fulltest"))
         return true;
   }

   return false;
}

static bool isPrintHelpOnly(ListCppObjT<CFString> * argList)
{
   for (int i = 0; i < static_cast<int>(argList->GetCount()); ++i) {
      if (*argList->Get(i) == _S("--help") || *argList->Get(i) == _S("-h")) {
         printf("Usage:\n\n");
         printf("Run normal test cases:\n");
         printf("> Testcppflib\n\n");
         printf("Run all test cases (include launching \"Testcppflib_2\") :\n");
         printf("> Testcppflib --fulltest\n\n");
         return true;
      }
   }

   return false;
}


static void PrintCppflibVersion()
{
    CFString ver(cppflib::GetflibVerString());
    printf("------------------------------\n");
    printf("cppflib version: %s\n", ver.ToUtf8String());
    printf("------------------------------\n");

#if defined(__ANDROID__)
    printf("@@@@ Debug messages are directed to DDMS ! @@@@\n");
#endif
}


#if defined(WIN32)
static ListCppObjT<CFString> *CollectArgs(int argc, _TCHAR* argv[])
#elif defined(linux)
static ListCppObjT<CFString> *CollectArgs(int argc, char * argv[])
#endif
{
    cppmempool::MemPoolWrap memPool;  // to collect memory blocks

    ListCppObjT<CFString> * argList = new ListCppObjT<CFString>();
    cppmempool::Retain(argList); // retain it since it needs to be returned

    for (int i = 0; i < argc; ++i) {
       argList->AddTail(new CFString(argv[i]));
    }

    PrintCppflibVersion();

    return argList;
}


#if defined(WIN32)
int _tmain(int argc, _TCHAR* argv[])
#elif defined(linux)
int main(int argc, char * argv[])
#endif
{
    setlocale(LC_CTYPE, "cht");

    cppmempool::GlobalInit();  // call this first

    ListCppObjT<CFString> * argList = CollectArgs(argc, argv);

    if (!isPrintHelpOnly(argList)) {
       bool isFullTest = isPerformFullTest(argList);

       ConfigXmlFileList(isFullTest);

       TestAllocation();
       TestCFString();
       TestCollections();
       TestThread(isFullTest);
       TestExceptions();
       TestLang();
       TestCustomClass();
       TestDataConversion();
       TestIO();
       TestUtil();
       TestNet();
       TestNetSSL();
       TestSqlite();
       TestHttp();
       TestXml();
       TestJSON();
       TestCrypto();
    }

    cppmempool::Release(argList);

    cppmempool::GlobalFinish();

    printf(">>>>>> End of testing ...\n");
    //printf(">>>>>> End of testing (Press ENTER to continue) ...\n");
    //getchar();   

#if defined(CHK_MEM_LEAK)
#   ifdef WIN32
       // dump any memory leak
       _CrtDumpMemoryLeaks();
#   endif
#endif
	return 0;
}

